/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package r.util;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 *
 * @author jcrada
 */
public class Functions {

    public static <T extends Number> String Scale(T value, T toMin, T toMax, T fromMin, T fromMax) {
        return "Scale(" + value + ", toMin=" + toMin + ", toMax=" + toMax
                + ", fromMin=" + fromMin + ", fromMax=" + fromMax + ")";
    }

    public static <T extends Number> String Scale(List<T> list, T toMin, T toMax) {
        return "Scale(" + Datatype.C(list) + ", toMin=" + toMin + ", toMax=" + toMax + ")";
    }

    public static <T extends Number> String Scale(List<T> list, T toMin, T toMax, T fromMin, T fromMax) {
        return "Scale(" + Datatype.C(list) + ", toMin=" + toMin + ", toMax=" + toMax
                + ", fromMin=" + fromMin + ", fromMax=" + fromMax + ")";
    }
    
    public static String Parameters(Map properties){
        Set keySet = properties.keySet();
        String result  = "";
        for (Iterator it = keySet.iterator(); it.hasNext(); ){
            Object key = it.next();
            result += key.toString() + " = " + ToR(properties.get(key));
            if (it.hasNext()) result+= ", ";
        }
        return result;
    }
    
    public static String ToR(Object o){
        if (o instanceof String || o instanceof Character){
            return "'" + o.toString() + "'";
        }else if (o instanceof Number){
            return o.toString();
        }
        return o.toString();
    }

    public static String DefineAllFunctions() {
        return DefineScale() + DefineTrapezoid() + DefineInverseTrapezoid() + DefinePrettyPairwiseWilcoxon();
    }

    public static String DefineScale() {
        return "#Scale: Scales a number to a different scale\n"
                + "Scale = function(value, toMin, toMax, fromMin=min(value), fromMax=max(value)){\n"
                + "(toMax - toMin) / (fromMax - fromMin) * (value - fromMin) + toMin;\n"
                + "}\n";
    }

    public static String DefineTrapezoid() {
        return "#Trapezoid: computes area under curve using trapezoidal rule\n"
                + "Trapezoid = function(x,y) {\nsum(diff(x)*(y[-1]+y[-length(y)]))/2;\n}\n";
    }

    public static String DefineInverseTrapezoid() {
        return "#InverseTrapezoid: computes area under curve using trapezoidal rule. Useful for using apply on dataframes\n"
                + "InverseTrapezoid = function(y,x) {\nTrapezoid(x,y);\n}\n";
    }

       public static String DefineStair() {
        String stair = "stair = function(x,y){\n"
                + "xl = c();\n"
                + "yl = c();\n"
                + "for (i in 1:length(x)){\n"
                + "	xl = c(xl, x[i]);\n"
                + "	yl = c(yl, y[i]);\n"
                + "	if (i < length(x)){\n"
                + "		xl = c(xl, x[i + 1]);\n"
                + "		yl = c(yl, y[i]);\n"
                + "	}\n"
                + "}\n"
                + "result= data.frame(x=xl,y=yl);\n"
                + "result;\n"
                + "}\n";
        return stair;
    }
    
    public static String DefinePrettyPairwiseWilcoxon() {
        return "#PrettyPairwiseWilcox: extracts information from pairwise.wilcox$pvalues and presents it by groups\n"
                + "PrettyPairwiseWilcox = function(t){                                          \n"
                + "    #format table                                                            \n"
                + "    t = rbind(NA,t);                                                         \n"
                + "    t = cbind(t,NA);                                                         \n"
                + "    for (i in 1:length(t[1,])){                                              \n"
                + "        for (j in i:length(t[i,])){                                          \n"
                + "        #complete triangular matrix                                          \n"
                + "        if (j == i) t[i,j] = '*'                                             \n"
                + "        else t[i,j] = switch(t[j,i], '+' = '-', '-' = '+', '=' = '=', '?');  \n"
                + "        }                                                                    \n"
                + "    }                                                                        \n"
                + "                                                                             \n"
                + "    labels = colnames(t);                                                    \n"
                + "     #remove empty label labels[-length(labels)]                             \n"
                + "    neighbors = unique(substring(labels[-length(labels)],1,2));              \n"
                + "    variants = unique(substring(labels[-length(labels)],3,3));               \n"
                + "                                                                             \n"
                + "    groups = length(variants);                                               \n"
                + "                                                                             \n"
                + "    result = matrix(NA, nrow = length(neighbors), ncol=groups);              \n"
                + "    rownames(result) = neighbors;                                            \n"
                + "    colnames(result) = variants;                                             \n"
                + "                                                                             \n"
                + "    tcol = 1; mrow = 1;                                                      \n"
                + "    for (trow in 1:length(t[,1])){                                           \n"
                + "        v = t[trow,tcol : (tcol + groups - 1)];                              \n"
                + "        mcol = ((trow - 1) %% groups) + 1; # 1 2 3, 1 2 3, 1 2 3             \n"
                + "        result[mrow,mcol] = paste(v, collapse='');                           \n"
                + "        if (trow %% groups == 0){                                            \n"
                + "         mrow = mrow + 1;                                                    \n"
                + "         tcol = tcol + groups;                                               \n"
                + "        }                                                                    \n"
                + "    }                                                                        \n"
                + "    result;                                                                  \n"
                + "}                                                                            \n";
    }

    public static String DefineEuclideanDistance(){
        return "#EuclideanDistance: computes the euclidean distance between two vectors\n"
                + "EuclideanDistance = function(x,y){\n"
                + "sqrt( sum((x - y)^2));\n}";
    }
}
